package sale.wxb.loveshopping.config;

import cn.hutool.core.util.StrUtil;
import com.github.xiaoymin.knife4j.spring.extension.OpenApiExtensionResolver;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.RequestMethod;
import sale.wxb.loveshopping.enums.ResponseEnum;
import springfox.documentation.builders.*;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.OperationBuilderPlugin;
import springfox.documentation.spi.service.contexts.OperationContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;

import java.util.*;
import java.util.stream.Collectors;

/**
 * Swagger 文档配置类
 */
@Configuration
@EnableSwagger2WebMvc
public class SwaggerConfig implements OperationBuilderPlugin {
    @Value("${swagger.enable}")
    private boolean enable;
    @Value("${swagger.title}")
    private String title;
    @Value("${swagger.desc}")
    private String desc;
    @Value("${swagger.version}")
    private String version;
    @Value("${swagger.author}")
    private String author;
    @Value("${swagger.email}")
    private String email;
    @Value("${swagger.package}")
    private String basePackage;

    /*引入Knife4j提供的扩展类*/
    private final OpenApiExtensionResolver openApiExtensionResolver;

    @Autowired
    public SwaggerConfig(OpenApiExtensionResolver openApiExtensionResolver) {
        this.openApiExtensionResolver = openApiExtensionResolver;
    }

    @Bean
    public Docket docket() {
        return new Docket(DocumentationType.SWAGGER_2)
                .enable(enable)
                // 移除默认的响应状态码
                .useDefaultResponseMessages(false)
                // 设置自己的响应状态码
                .globalResponseMessage(RequestMethod.GET, responseMessageList())
                .globalResponseMessage(RequestMethod.POST, responseMessageList())
                .apiInfo(getApiInfo())
                .groupName("admin")
                .select()
                .apis(RequestHandlerSelectors.basePackage(basePackage))
                .paths(PathSelectors.any())
                .build()
                .extensions(openApiExtensionResolver.buildSettingExtensions());
    }

    /**
     * Api信息
     * @return ApiInfo
     */
    private ApiInfo getApiInfo() {
        return new ApiInfoBuilder()
                .title(title)
                .description(desc)
                .version(version)
                .contact(new Contact(author, "" , email))
                .build();
    }

    /**
     * 设置自定义响应状态码
     * @return List<ResponseMessage>
     */
    private List<ResponseMessage> responseMessageList() {
        List<ResponseMessage> messages = new ArrayList<>();
        Arrays.stream(ResponseEnum.values()).forEach(x -> {
            messages.add(
                    new ResponseMessageBuilder()
                            .code(x.getCode())
                            .message(x.getMessage())
                            .build()
            );
        });
        return messages;
    }

    // 重置 operationId ID 目的是为了第三方生成代码时自定义方法名
    private void resetUniqueId(OperationContext context) {
        // 剔除控制器不需要的部分
        String controllerName = Arrays.stream(
                context.getGroupName()
                        .replace("-controller", "")
                        .split("-"))
                .map(StrUtil::upperFirst)
                .collect(Collectors.joining());
        String firstStr = StrUtil.isEmpty(controllerName) ? "" : StrUtil.lowerFirst(controllerName);
        String fillId = firstStr + StrUtil.upperFirst(context.getName());
        context.operationBuilder().uniqueId(fillId).codegenMethodNameStem(fillId);
    }

    @Override
    public void apply(OperationContext context) {
        resetUniqueId(context);
    }

    @Override
    public boolean supports(DocumentationType documentationType) {
        return true;
    }
}

